package com.example.demo.service;

import com.alibaba.fastjson.JSON;
import com.example.demo.bean.Buy;
import com.example.demo.bean.Good;
import com.example.demo.bean.ShopConfig;
import com.example.demo.service.impl.CommonBuyStrategy;
import com.example.demo.service.impl.DiscountBuyStrategy;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName: Buy
 * @Description: 超市商品购买
 * @Author: Willka
 * @Date: Created in 2022/11/19 13:33
 */
@Slf4j
@Service
public class Shop {

    //商品 Map
    Map<String, Good> goodMap = Maps.newHashMap();

    /**
     * 初始化商品
     *
     * @param good
     */
    public void initGoods(List<Good> goods) {
        for (Good good : goods) {
            String name = good.getName();
            goodMap.put(name, good);
        }
        log.debug("Goods init success ! ");
    }

    /**
     * 初始化商店全局配置
     *
     * @param isFullReduction
     * @param reductionRules
     */
    public void initShopConfig(boolean isFullReduction, Map<BigDecimal, BigDecimal> reductionRules) {
        ShopConfig shopConfig = ShopConfig.getInstance();
        shopConfig.setFullReduction(isFullReduction);
        shopConfig.setReductionRules(reductionRules);
        if (!CollectionUtils.isEmpty(reductionRules)) {
            shopConfig.setReductionList(reductionRules.keySet().stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()));
        }
    }

    public BigDecimal calculate(List<Buy> buyList) throws Exception {
        if(CollectionUtils.isEmpty(buyList)){
            throw new Exception("Input is null or empty!");
        }
        log.info("[Shop][calculate] request list:{}", JSON.toJSONString(buyList));
        BigDecimal result = new BigDecimal(0);
        BigDecimal tempResult = new BigDecimal(0);
        //遍历获取金额
        for (Buy buy : buyList) {
            BigInteger check = new BigInteger(String.valueOf(0));
            try {
                check = buy.getNum().toBigIntegerExact();
            }catch (ArithmeticException e){
                log.error("Input num is not the integer",e);
            }catch (Exception e){
                e.printStackTrace();
            }
            if(check.compareTo(new BigInteger(String.valueOf(0))) <= 0){
                throw new Exception("Input num is not the positive integer");
            }
            String name = buy.getName();
            if (goodMap.containsKey(name)) {
                log.debug("[Shop][calculate] {} exists in the goods list !", name);
                Good good = goodMap.get(name);
                Context context = new Context(good.getIsSalesPromotion() ? new DiscountBuyStrategy() : new CommonBuyStrategy());
                try {
                    tempResult = context.calculate(good, buy.getNum());
                } catch (Exception e) {
                    log.error("There are something error! ", e);
                }
                result = result.add(tempResult);
            } else {
                log.warn("[Shop][calculate] {} does not exist in the goods list !", name);
            }
        }
        //获取商店配置
        ShopConfig shopConfig = ShopConfig.getInstance();
        //商店是否有满减促销活动
        if (shopConfig.getFullReduction()) {
            for (BigDecimal fullReduction : shopConfig.getReductionList()) {
                if (result.compareTo(fullReduction) > 0) {
                    //获得匹配的满减规则
                    BigDecimal reduction = shopConfig.getReductionRules().get(fullReduction);
                    //求取满减次数
                    BigDecimal num = result.divideToIntegralValue(fullReduction);
                    //计算出满减后的总金额
                    result = result.subtract(reduction.multiply(num));
                }
            }
        }
        return result;
    }

}